// sparseVector v = new sparseVector(100); //size constructor; size is 100.
//     v.set(0, 1.0);
//     v.set(3, 2.0);
//     v.set(80,-4.5);

//     System.out.println(v.get(80)); //should print -4.5
//     System.out.println(v.get(50)); //should print 0.0

//     try {
//        System.out.println(v.get(101)); //error -- index out of range
//        throw new IllegalStateException("We should not get here, an exception should have been thrown");
//     } catch (IndexOutOfBoundsException t) {
//        // success
//     }
//     System.out.println(v.toString()); //should print something like [1.0, 0.0, 0.0, 2.0, 0.0, ...]

package main

import (
	"errors"
	"fmt"
)

type Node struct {
	index int
	value float64
	next  *Node
}

type SparseVector2 struct {
	capacity int
	size     int
	head     *Node
}

func newSV2(size int) *SparseVector2 {
	return &SparseVector2{
		capacity: size,
		size:     0,
		head:     nil,
	}
}

func (this *SparseVector2) cap() int {
	return this.capacity
}

func (this *SparseVector2) len() int {
	return this.size
}

func (this *SparseVector2) get(index int) (float64, error) {
	if index < this.capacity {
		curr := this.head
		// fmt.Println(this.head)
		for curr != nil {
			if index == curr.index {
				return curr.value, nil
			} else {
				curr = curr.next
			}
		}
	} else {
		return 0.0, errors.New("index out of range")
	}
	return 0.0, nil
}

func (this *SparseVector2) set(index int, value float64) error {
	if index >= this.capacity {
		return errors.New("index out of range")
	}
	newNode := &Node{
		index: index,
		value: value,
		next:  nil,
	}
	if this.head == nil {
		this.head = newNode
		return nil
	}

	curr := this.head

	for curr.next != nil {
		curr = curr.next
	}
	curr.next = newNode
	this.size += 1
	// fmt.Println(this.head)
	// fmt.Println(this.head.next)
	return nil
}

// ----------------------------------------------------------------
// func (this *SparseVector) New(size int) *SparseVector {
// 	return &SparseVector{
// 		size:   size,
// 		matrix: make(map[int]float64),
// 	}
// }
type SparseVector struct {
	size   int
	matrix map[int]float64
}

func newSV(size int) *SparseVector {
	return &SparseVector{
		size:   size,
		matrix: make(map[int]float64),
	}
}

func (this *SparseVector) capacity() int {
	return this.size
}

func (this *SparseVector) length() int {
	return len(this.matrix)
}

func (this *SparseVector) toString() string {
	res := "["
	for i := 0; i < this.size; i++ {
		if _, ok := this.matrix[i]; ok == true {
			res = res + fmt.Sprintf("%g", this.matrix[i]) + ", "
			// value, _ := strconv.ParseFloat(this.matrix[i], 64)
		} else {
			res += "0.0, "
		}
	}
	return res[:len(res)-2] + "]"
}

func (this *SparseVector) set(index int, value float64) error {
	if index >= this.size {
		return errors.New("index out of range")
	}
	this.matrix[index] = value
	return nil
}

func (this *SparseVector) get(index int) (float64, error) {
	if index < this.size {
		if _, ok := this.matrix[index]; ok == false {
			return 0.0, nil
		} else {
			return this.matrix[index], nil
		}
	} else {
		return 0, errors.New("index out of range")
	}
}

func main() {
	// sv := newSV(10)
	// sv.set(1, 100.1)
	// fmt.Println(sv.get(0))
	// fmt.Println(sv.get(1))
	// fmt.Println(sv.toString())
	sv2 := newSV2(10)
	fmt.Println(sv2.cap())
	fmt.Println(sv2.get(0))
	fmt.Println(sv2.get(1))
	sv2.set(1, 10.0)
	fmt.Println(sv2.get(1))
	fmt.Println(sv2.get(2))
}
